import { Disposable, Event, EventEmitter, FileChangeEvent, FileChangeType, FileStat, FileSystemError, FileSystemProvider, FileType, Uri } from 'vscode';
import { manage } from '../../preview-manager';
import { log } from '../../utils';
import { PreviewFile } from './preview-file';

/**
 * 预览文件系统
 *
 * @author chitanda
 * @date 2022-01-17 15:01:47
 * @export
 * @class PreviewSystemProvider
 * @implements {FileSystemProvider}
 */
export class PreviewSystemProvider implements FileSystemProvider {
  protected entries: Map<string, PreviewFile> = new Map();
  /**
   * 文件变更事件
   *
   * @author chitanda
   * @date 2021-11-09 09:11:08
   * @private
   */
  private emitter = new EventEmitter<FileChangeEvent[]>();

  onDidChangeFile: Event<FileChangeEvent[]> = this.emitter.event;

  watch(uri: Uri, options: { recursive: boolean; excludes: string[] }): Disposable {
    log.info(`PreviewSystemProvider.watch: ${uri.fsPath}`);
    return new Disposable(() => {});
  }

  async stat(uri: Uri): Promise<FileStat> {
    console.log(`PreviewSystemProvider.stat: ${uri.path}`);
    return this.getFile(uri);
  }

  async readDirectory(uri: Uri): Promise<[string, FileType][]> {
    log.info(`PreviewSystemProvider.readDirectory: ${uri.fsPath}`);
    return [];
  }

  async createDirectory(uri: Uri): Promise<void> {
    log.info(`PreviewSystemProvider.createDirectory: ${uri.fsPath}`);
  }

  async readFile(uri: Uri): Promise<Uint8Array> {
    console.log(`PreviewSystemProvider.readFile: ${uri.fsPath}`);
    const file = await this.getFile(uri);
    return file.unit8content;
  }

  async writeFile(uri: Uri, content: Uint8Array, options: { create: boolean; overwrite: boolean }): Promise<void> {
    if (options.create) {
      const file = new PreviewFile();
      file.unit8content = content;
      this.entries.set(uri.path, file);
      this.emitter.fire([{ type: FileChangeType.Created, uri }]);
    } else {
      const file = await this.getFile(uri);
      file.unit8content = content;
      this.emitter.fire([{ type: FileChangeType.Created, uri }]);
    }
  }

  async delete(uri: Uri, _options: { recursive: boolean }): Promise<void> {
    this.entries.delete(uri.path);
  }

  async rename(oldUri: Uri, newUri: Uri, _options: { overwrite: boolean }): Promise<void> {
    log.info(`PreviewSystemProvider.rename: ${oldUri.fsPath} => ${newUri.fsPath}`);
  }

  /**
   * 获取文件，不存在则抛异常
   *
   * @author chitanda
   * @date 2022-02-10 17:02:03
   * @protected
   * @param {Uri} uri
   * @return {*}  {Promise<PreviewFile>}
   */
  protected async getFile(uri: Uri): Promise<PreviewFile> {
    const file = this.entries.get(uri.path);
    if (file) {
      return file;
    }
    const bol = await manage.repreview(uri);
    if (bol) {
      return this.entries.get(uri.path)!;
    }
    throw FileSystemError.FileNotFound(uri);
  }

  /**
   * 查找文件
   *
   * @author chitanda
   * @date 2022-01-18 15:01:46
   * @param {Uri} uri
   * @return {*}  {(PreviewFile | null)}
   */
  findFile(uri: Uri): PreviewFile | null {
    if (this.entries.has(uri.path)) {
      return this.entries.get(uri.path)!;
    }
    return null;
  }
}
